#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<arpa/inet.h>
#include<sys/socket.h>
 
typedef struct
{
  int fd;
  struct sockaddr_in addr;
} Socket;
 
void die(char *s)
{
    perror(s);
    exit(1);
}

Socket *udpSocket(char *address, int port, int broadcast)
{
  Socket *s = (Socket *)malloc(sizeof(Socket));

  if(!s) goto ERR;

  int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if(fd==-1) goto ERR;

  if(broadcast)
  {
    setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
  }

  s->fd = fd;

  memset((char *) &s->addr, 0, sizeof(s->addr));
  s->addr.sin_family = AF_INET;
  s->addr.sin_port = htons(port);

  if (inet_aton(address , &s->addr.sin_addr) == 0) goto ERR;

  return s;

ERR:
  if(fd!=-1) close(fd);
  if(s) free(s);

  return 0;
}

void destroyUdpSocket(Socket *s)
{
  close(s->fd);
  free(s);
}

int udpWrite(Socket *s, uint8_t *buf, int sz)
{
  int addrLen = sizeof(s->addr);

  return sendto(s->fd, buf, sz, 0, (struct sockaddr *)&s->addr, addrLen);
}

int udpRead(Socket *s, uint8_t *buf, int bufSz)
{
  int addrLen = sizeof(s->addr);

  return recvfrom(s->fd, buf, bufSz, 0, (struct sockaddr *)&s->addr, &addrLen);
}

#define BUFLEN 512  //Max length of buffer
void portCmd(Socket *s, char cmd)
{
  char buf[BUFLEN];
  uint32_t command[2];
  char c;

  printf("numero da porta [0 - 9]: ");
  fflush(stdout);
  fgets(buf,BUFLEN,stdin);
  c = buf[0];

  command[0] = cmd - '0';
  command[1] = c - '0';

  printf("Enviando comando... %x %x\n",command[0],command[1]);
  int n = udpWrite(s,(uint8_t *)command, sizeof(command));
  printf("Comando enviado! %d bytes\n",n);
}

#define SERVER "192.168.25.5"
#define PORT 5000   //The port on which to send data
int main(void)
{
  Socket *s = udpSocket(SERVER,PORT,0);
  char buf[BUFLEN];

  while(1)
  {
    char cmd;
    printf("0- Desligar\n1- Ligar\n: ");
    fflush(stdout);
    fgets(buf,BUFLEN,stdin);
    cmd = buf[0];

    switch(cmd)
    {
      case '0':
      case '1': portCmd(s,cmd); break;
      default: printf("Comando invalido!\n"); continue;
    }

    printf("Esperando resposta do comando...\n");
    udpRead(s,buf,BUFLEN);
    printf("R: %s\n",buf);
  }

  destroyUdpSocket(s);

  return 0;
}
